package org.acghub.mtdb.common;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author zhouhe
 */
public interface INaming<S extends INaming> {
    String getName();

    Root getRoot();

    S getParent();

    Set<S> getChildren();

    default <T extends INaming> List<T> getChildren(Class<T> clazz) {
        List<T> list = new ArrayList<>();
        for (INaming child : getChildren()) {
            if (clazz.isInstance(child)) {
                list.add(clazz.cast(child));
            }
        }
        return list;
    }

    default <T extends INaming> T getChild(Class<T> clazz, String name) {
        for (INaming child : getChildren()) {
            if (clazz.isInstance(child) && child.getName().equals(name)) {
                return clazz.cast(child);
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private <T extends Naming> void getDescendants0(List<T> list, Class<T> clazz) {
        for (INaming child : getChildren()) {
            if (clazz.isInstance(child)) {
                list.add(clazz.cast(child));
            }
            child.getDescendants0(list, clazz);
        }
    }

    default <T extends Naming> List<T> getDescendants(Class<T> clazz) {
        List<T> list = new ArrayList<>();
        getDescendants0(list, clazz);
        return list;
    }

}
